package com.rd.p2p.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.Button;
import com.foxinmy.weixin4j.mp.WeixinProxy;
import com.foxinmy.weixin4j.mp.message.TemplateMessage;
import com.foxinmy.weixin4j.type.ButtonType;
import com.qd.p2p.weixin.service.WeiXinService;
import com.qdlc.p2p.biz.service.WeChatMenuService;
import com.qdlc.p2p.common.core.queue.QueueHandlers;
import com.qdlc.p2p.common.core.queue.ValueEvent;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.web.filter.SimplePropertyFilter;
import com.qdlc.p2p.dal.dto.WeChatMenu;
import com.qdlc.p2p.dal.model.WeChatMenuModel;
import com.rd.p2p.app.enums.WeChatButtonType;

@Service("weiXinService")
public class WeiXinServiceImpl implements WeiXinService {
	private static final Logger LOG = LoggerFactory.getLogger(WeiXinServiceImpl.class);

	@Resource
    private WeChatMenuService weChatMenuService;

    private Map<String, Object> data;

	@Override
	public void sendTemplateMessages(List<String> toUsers, String templateId, String title, String url,
			Map<String, String> data) {
		Collection<ValueEvent> events = new ArrayList<ValueEvent>();
		for (String openId : toUsers) {
			SendTemplateMessageEvent event = new SendTemplateMessageEvent();
			event.setToUser(openId);
			event.setTemplateId(templateId);
			event.setTitle(title);
			event.setUrl(url);
			event.setData(data);
			events.add(event);
		}
        QueueHandlers.submit(events);
	}

	@Override
	public Boolean sendTemplateMessage(String toUser, String templateId, String title, String url,
			Map<String, String> data) {
		WeixinProxy wp = new WeixinProxy();
		TemplateMessage tm = new TemplateMessage(toUser, templateId, title, url);
		if (data != null) {
			for (Entry<String, String> entry : data.entrySet()) {
				tm.pushData(entry.getKey(), entry.getValue());
			}
		}
		try {
			wp.sendTmplMessage(tm);
			LOG.debug("发送微信信息至:" + toUser);
			return true;
		} catch (WeixinException e) {
			LOG.error(e.getMessage());
		}
		return false;
	}

    /* (non-Javadoc)
     * @see com.qd.p2p.weixin.service.WeiXinService#createWeChatMenu(java.lang.String, java.lang.String, java.lang.Long, java.lang.Byte, java.lang.Byte)
     */
    @Override
    public String createWeChatMenu(String menuName, String menuContent, Long parentId, Byte level,Byte type) {
        // 将微信菜单保存到数据库
        WeChatMenu addWeChatMenu;
        try {
            WeChatMenuModel model = new WeChatMenuModel(menuName, menuContent, parentId, level, type);
            // 校验参数
            model.validWeChatMenuModel();
            WeChatMenu weChatMenu = weChatMenuService.findWeChatMenuById(parentId);
            if (null == weChatMenu
                    && WeChatMenuModel.LEVEL_1 != level) { // 一级菜单无需父级Id
                throw new BusinessException("创建菜单的父级菜单不存在！");
            }
            // 获取所有可用一级菜单
            List<WeChatMenuModel> level1MenuList = this.weChatMenuService.listByLevelAndIsDelete(WeChatMenuModel.LEVEL_1, false);
            if (level1MenuList.size() >= WeChatMenuModel.LEVEL_1_MAX_NUM
                    && WeChatMenuModel.LEVEL_1 == level) {
                throw new BusinessException("微信一级菜单最多只能创建" + WeChatMenuModel.LEVEL_1_MAX_NUM + "个，不能再添加！");
            }
            // 获取添加菜单的父菜单的子菜单数目
            List<WeChatMenuModel> subMemuList = this.weChatMenuService.listByParentIdAndIsDelete(parentId, false);
            if (subMemuList.size() >= WeChatMenuModel.LEVEL_2_MAX_NUM
                    && WeChatMenuModel.LEVEL_2 == level) {
                throw new BusinessException("微信二级菜单最多只能创建" + WeChatMenuModel.LEVEL_2_MAX_NUM + "个，不能再添加！");
            }
            if (WeChatMenuModel.LEVEL_1 == level) {
                level1MenuList.add(model);
            }
            // 调用微信接口创建微信菜单
            WeixinProxy wp = new WeixinProxy();
            // 所有菜单(微信只需考虑两级菜单)
            List<Button> allBtnList = new ArrayList<Button>();
            for (WeChatMenuModel level1Menu : level1MenuList) {

                ButtonType level1ButtonType = WeChatButtonType.getValue(level1Menu.getButtonType());
                if (null != level1ButtonType) {
                    Button menuItem = new Button(level1Menu.getName(), level1Menu.getContent(), level1ButtonType);

                    long level1MenuId = level1Menu.getId();
                    if (level1MenuId > 0L) { // 去掉刚添加的二级菜单
                        // 二级菜单
                        List<WeChatMenuModel> level2MenuList = new ArrayList<WeChatMenuModel>();
                        List<WeChatMenuModel> menuList = this.weChatMenuService
                                .listByParentIdAndIsDelete(level1MenuId, false);
                        // 二级菜单和一级菜单(默认根据sort升序)的顺序相反，需要降序
                        Collections.reverse(menuList);
                        if (WeChatMenuModel.LEVEL_2 == level
                                && parentId == level1Menu.getId()) {
                            level2MenuList.add(model);
                        }
                        level2MenuList.addAll(menuList);
                        if (level2MenuList.size() > 0) {
                            List<Button> level2Btn = new ArrayList<Button>();
                            for (WeChatMenuModel level2Menu : level2MenuList) {
                                ButtonType level2ButtonType = WeChatButtonType.getValue(level2Menu.getButtonType());
                                if (null != level2ButtonType) {
                                    level2Btn.add(new Button(level2Menu.getName(), level2Menu.getContent(), level2ButtonType));
                                }
                            }
                            menuItem.setSubs(level2Btn);
                        }
                    }
                    allBtnList.add(menuItem);
                }
            }
            try {
                wp.createMenu(allBtnList);
            } catch (Exception e) {
                throw new BusinessException("调用微信平台接口创建菜单异常！");
            }
            addWeChatMenu = this.weChatMenuService.addWeChatMenu(model.prototype());
        } catch (Exception e) {
            LOG.error(e.getMessage());
            return buildResultStr(e.getMessage(), false);
        }

        data = new HashMap<String, Object>();
        data.put("msg", "创建菜单成功");
        data.put("result", true);
        data.put("weChatMenu", addWeChatMenu);
        return getStringOfJpaObj(data);
    }

    /* (non-Javadoc)
     * @see com.qd.p2p.weixin.service.WeiXinService#updateWeChatMenu(java.lang.Long, java.lang.String, java.lang.String, java.lang.Byte)
     */
    @Override
    public String updateWeChatMenu(Long menuId, String menuName, String menuContent, Byte buttonType) {
        // 将微信菜单保存到数据库
        WeChatMenu updateWeChatMenu;
        try {
            WeChatMenu weChatMenu = weChatMenuService.findWeChatMenuById(menuId);
            if (null == weChatMenu) {
                throw new BusinessException("需要修改菜单不存在！");
            }
            byte level = weChatMenu.getLevel();

            // 需要校验的数据
            WeChatMenuModel model = new WeChatMenuModel(menuName, menuContent, level, buttonType );

            // 校验参数
            model.validWeChatMenuModel();
            // 获取所有可用一级菜单
            List<WeChatMenuModel> level1MenuList = this.weChatMenuService
                    .listByLevelAndIsDelete(WeChatMenuModel.LEVEL_1, false);
            // 调用微信接口创建微信菜单
            WeixinProxy wp = new WeixinProxy();
            // 所有菜单(微信只需考虑两级菜单)
            List<Button> allBtnList = new ArrayList<Button>();
            for (WeChatMenuModel level1Menu : level1MenuList) {
                ButtonType level1ButtonType = WeChatButtonType.getValue(level1Menu.getButtonType());
                if (null != level1ButtonType) {
                    if (WeChatMenuModel.LEVEL_1 == level
                            && level1Menu.getId() == menuId) {
                        level1Menu.setName(menuName);
                        level1Menu.setContent(menuContent);
                    }

                    Button menuItem = new Button(level1Menu.getName(), level1Menu.getContent(), level1ButtonType);
                    // 二级菜单
                    List<WeChatMenuModel> level2MenuList = this.weChatMenuService
                            .listByParentIdAndIsDelete(level1Menu.getId(), false);
                    if (level2MenuList.size() > 0) {
                        // 二级菜单和一级菜单(默认根据sort升序)的顺序相反，需要降序
                        Collections.reverse(level2MenuList);
                        List<Button> level2Btn = new ArrayList<Button>();
                        for (WeChatMenuModel level2Menu : level2MenuList) {
                            if (WeChatMenuModel.LEVEL_1 == level
                                    && level2Menu.getId() == menuId) {
                                level2Menu.setName(menuName);
                                level2Menu.setContent(menuContent);
                            }
                            ButtonType level2ButtonType = WeChatButtonType.getValue(level2Menu.getButtonType());
                            if (null != level2ButtonType) {
                                level2Btn.add(
                                        new Button(level2Menu.getName(), level2Menu.getContent(), level2ButtonType));
                            }
                        }
                        menuItem.setSubs(level2Btn);
                    }
                    allBtnList.add(menuItem);
                }
            }
            try {
                wp.createMenu(allBtnList);
            } catch (Exception e) {
                LOG.error(e.getMessage());
                throw new BusinessException("调用微信平台接口修改菜单异常！");
            }

            // 需要更新的字段
            weChatMenu.setName(StringUtil.isNull(menuName));
            weChatMenu.setContent(StringUtil.isNull(menuContent));
            weChatMenu.setLevel(level);
            weChatMenu.setButtonType(buttonType);
            updateWeChatMenu = this.weChatMenuService.updateWeChatMenu(weChatMenu);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            return buildResultStr(e.getMessage(), false);
        }

        data = new HashMap<String, Object>();
        data.put("msg", "修改菜单成功");
        data.put("result", true);
        data.put("weChatMenu", updateWeChatMenu);
        return getStringOfJpaObj(data);
    }

    /* (non-Javadoc)
     * @see com.qd.p2p.weixin.service.WeiXinService#deleteWeChatMenu(java.lang.Long)
     */
    @Override
    public String deleteWeChatMenu(Long menuId) {
        try {
            WeChatMenu weChatMenu = weChatMenuService.findWeChatMenuById(menuId);
            if (null == weChatMenu) {
                throw new BusinessException("需要修改菜单不存在！");
            }

            // 需要删除的菜单ids
            Set<Long> removeIds = new HashSet<Long>();
            removeIds.add(menuId);
            List<WeChatMenuModel> subMenuList = weChatMenuService.listByParentIdAndIsDelete(menuId, false);
            for (WeChatMenuModel weChatMenuModel : subMenuList) {
                removeIds.add(weChatMenuModel.getId());
            }

            // 获取所有可用一级菜单
            List<WeChatMenuModel> level1MenuList = this.weChatMenuService
                    .listByLevelAndIsDelete(WeChatMenuModel.LEVEL_1, false);
            // 调用微信接口创建微信菜单
            WeixinProxy wp = new WeixinProxy();
            // 所有菜单(微信只需考虑两级菜单)
            List<Button> allBtnList = new ArrayList<Button>();
            for (WeChatMenuModel level1Menu : level1MenuList) {
                ButtonType level1ButtonType = WeChatButtonType.getValue(level1Menu.getButtonType());
                if (null != level1ButtonType) {
                    if (removeIds.contains(level1Menu.getId())) { // 过滤要删除的菜单
                        continue;
                    }

                    Button menuItem = new Button(level1Menu.getName(), level1Menu.getContent(), level1ButtonType);
                    // 二级菜单
                    List<WeChatMenuModel> level2MenuList = this.weChatMenuService
                            .listByParentIdAndIsDelete(level1Menu.getId(), false);
                    if (level2MenuList.size() > 0) {
                        // 二级菜单和一级菜单(默认根据sort升序)的顺序相反，需要降序
                        Collections.reverse(level2MenuList);
                        List<Button> level2Btn = new ArrayList<Button>();
                        for (WeChatMenuModel level2Menu : level2MenuList) {
                            if (removeIds.contains(level2Menu.getId())) { // 过滤要删除的菜单
                                continue;
                            }
                            ButtonType level2ButtonType = WeChatButtonType.getValue(level2Menu.getButtonType());
                            if (null != level2ButtonType) {
                                level2Btn.add(new Button(level2Menu.getName(), level2Menu.getContent(), level2ButtonType));
                            }
                        }
                        menuItem.setSubs(level2Btn);
                    }
                    allBtnList.add(menuItem);
                }
            }
            try {
                wp.createMenu(allBtnList);
            } catch (Exception e) {
                LOG.error(e.getMessage());
                throw new BusinessException("调用微信平台接口创建菜单异常！");
            }
            // 将微信菜单从数据库中删除(逻辑上删除)
            this.weChatMenuService.deleteWeChatMenu(weChatMenu);
            this.weChatMenuService.deleteByParentId(menuId);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            return buildResultStr(e.getMessage(), false);
        }
        data = new HashMap<String, Object>();
        data.put("msg", "删除菜单成功");
        data.put("result", true);
        return getStringOfJpaObj(data);
    }

    /* (non-Javadoc)
     * @see com.qd.p2p.weixin.service.WeiXinService#listWeChatMenus(java.lang.Boolean)
     */
    @Override
    public String listWeChatMenus(Boolean isDelete) {
        List<WeChatMenuModel> weChatMenuList = this.weChatMenuService.listModelsByIsDelete(isDelete);
        data = new HashMap<String, Object>();
        data.put("data", weChatMenuList);
        data.put("msg", "获取所有菜单成功");
        data.put("result", true);
        return getStringOfJpaObj(data);
    }

    /**
     * <p>对象转换成字符串</p>
     * @author Kaiju Zhao 2016年1月19日 下午2:42:47
     * @param obj
     * @return
     * @modificationHistory=========================逻辑或功能性重大变更记录
     * @modify by user: {修改人} 2016年1月19日 下午2:42:47
     * @modify by reason:{原因}
     */
    private String getStringOfJpaObj(Object obj) {
        SimplePropertyFilter spf = new SimplePropertyFilter();
        SerializeWriter sw = new SerializeWriter();
        JSONSerializer serializer = new JSONSerializer(sw);
        serializer.getPropertyFilters().add(spf);
        serializer.write(obj);
        return sw.toString();
    }

    /* (non-Javadoc)
     * @see com.qd.p2p.weixin.service.WeiXinService#pushAllMenusToMP()
     */
    @Override
    public String pushAllMenusToMP() {
        try {
            // 获取所有可用一级菜单
            List<WeChatMenuModel> level1MenuList = this.weChatMenuService
                    .listByLevelAndIsDelete(WeChatMenuModel.LEVEL_1, false);
            // 调用微信接口创建微信菜单
            WeixinProxy wp = new WeixinProxy();
            // 所有菜单(微信只需考虑两级菜单)
            List<Button> allBtnList = new ArrayList<Button>();
            for (WeChatMenuModel level1Menu : level1MenuList) {
                ButtonType level1ButtonType = WeChatButtonType.getValue(level1Menu.getButtonType());
                if (null != level1ButtonType) {
                    Button menuItem = new Button(level1Menu.getName(), level1Menu.getContent(), level1ButtonType);
                    // 二级菜单
                    List<WeChatMenuModel> level2MenuList = this.weChatMenuService
                            .listByParentIdAndIsDelete(level1Menu.getId(), false);
                    if (level2MenuList.size() > 0) {
                        // 二级菜单和一级菜单(默认根据sort升序)的顺序相反，需要降序
                        Collections.reverse(level2MenuList);
                        List<Button> level2Btn = new ArrayList<Button>();
                        for (WeChatMenuModel level2Menu : level2MenuList) {
                            ButtonType level2ButtonType = WeChatButtonType.getValue(level2Menu.getButtonType());
                            if (null != level2ButtonType) {
                                level2Btn.add(new Button(level2Menu.getName(), level2Menu.getContent(), level2ButtonType));
                            }
                        }
                        menuItem.setSubs(level2Btn);
                    }
                    allBtnList.add(menuItem);
                }
            }
            try {
                wp.createMenu(allBtnList);
            } catch (Exception e) {
                LOG.error(e.getMessage());
                throw new BusinessException("调用微信平台接口推送所有菜单到微信公众平台异常！");
            }
        } catch (Exception e) {
            LOG.error(e.getMessage());
            return buildResultStr(e.getMessage(), false);
        }
        return buildResultStr("推送到微信公众平台成功", true);
    }

    /**
     * <p>组装返回参数</p>
     * @author Kaiju Zhao 2016年1月19日 下午6:49:22
     * @param msg
     * @param result
     * @return
     * @modificationHistory=========================逻辑或功能性重大变更记录
     * @modify by user: {修改人} 2016年1月19日 下午6:49:22
     * @modify by reason:{原因}
     */
    private String buildResultStr(String msg, boolean result) {
        HashMap<String, Object> data = new HashMap<String, Object>();
        data.put("msg", msg);
        data.put("result", result);
        return getStringOfJpaObj(data);
    }
}
